package com.example.gobang.service;

import com.example.gobang.constant.Constants;
import com.example.gobang.manager.OnlineUserManager;
import com.example.gobang.manager.RoomManager;
import com.example.gobang.model.Result;
import com.example.gobang.model.Room;
import com.example.gobang.model.UserInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Service
@Slf4j
// 负责完成整个匹配功能
public class MatchService {
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RoomManager roomManager;
    // 创建三个队列，分别用于匹配不同天梯分数的玩家
    private Queue<UserInfo> normalQueue = new LinkedList<>();
    private Queue<UserInfo> highQueue = new LinkedList<>();
    private Queue<UserInfo> veryHighQueue = new LinkedList<>();

    // 将玩家放入匹配队列
    public void add(UserInfo userInfo) {
        // 参数校验
        if(userInfo == null) {
            return;
        }
        // 添加
        if(userInfo.getScore() < Constants.HIGH_SCORE) {
            synchronized (normalQueue) {
                normalQueue.offer(userInfo);
                normalQueue.notify();
            }
            log.info("将玩家 {} 放入 normalQueue 中", userInfo.getUserName());
        }else if(userInfo.getScore() >= Constants.HIGH_SCORE && userInfo.getScore() < Constants.VERY_HIGH_SCORE) {
            synchronized (highQueue) {
                highQueue.offer(userInfo);
                highQueue.notify();
            }
            log.info("将玩家 {} 放入 highQueue 中", userInfo.getUserName());
        }else {
            synchronized (veryHighQueue) {
                veryHighQueue.offer(userInfo);
                veryHighQueue.notify();
            }
            log.info("将玩家 {} 放入 veryHighQueue 中", userInfo.getUserName());
        }
    }
    // 将玩家从匹配队列中移除
    public void remove(UserInfo userInfo) {
        // 参数校验
        if(userInfo.getUserId() <= 0) {
            return;
        }
        // 移除
        if(userInfo.getScore() <= Constants.HIGH_SCORE) {
            synchronized (normalQueue) {
                normalQueue.remove(userInfo);
            }
            log.info("将玩家 {} 从 normalQueue 中移除", userInfo.getUserName());
        } else if (userInfo.getScore() >= Constants.HIGH_SCORE && userInfo.getScore() < Constants.VERY_HIGH_SCORE) {
            synchronized (highQueue) {
                highQueue.remove(userInfo);
            }
            log.info("将玩家 {} 从 highQueue 中移除", userInfo.getUserName());
        } else {
            synchronized (veryHighQueue) {
                veryHighQueue.remove(userInfo);
            }
            log.info("将玩家 {} 从 veryHighQueue 中移除", userInfo.getUserName());
        }
    }

    public MatchService() {
        // 创建扫描线程，进行匹配
        Thread normalThread = new Thread(() -> {
            while (true) {
                handlerMatch(normalQueue);
            }
        });

        Thread highThread = new Thread(() -> {
            while (true) {
                handlerMatch(highQueue);
            }
        });

        Thread veryHighThread = new Thread(() -> {
            while (true) {
                handlerMatch(veryHighQueue);
            }
        });
        normalThread.start();
        highThread.start();
        veryHighThread.start();
    }
    public void handlerMatch(Queue<UserInfo> queue) {
        try {
            synchronized (queue) {
                // 若队列为空 或 队列中只有一个玩家信息，则阻塞等待
                while (queue.size() <= 1) {
                    queue.wait();
                }
                // 取出两个玩家进行匹配
                UserInfo user1 = queue.poll();
                UserInfo user2 = queue.poll();
                // 通知两个玩家已经匹配到了对手
                WebSocketSession session1 = onlineUserManager.getFromHall(user1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromHall(user2.getUserId());
                if(session1 == null) {
                    queue.offer(user2);
                    log.info("将玩家 {} 重新放回匹配队列中", user1.getUserName());
                    return;
                } else if (session2 == null) {
                    queue.offer(user1);
                    log.info("将玩家 {} 重新放回匹配队列中", user2.getUserName());
                    return;
                }
                // 为这两个玩家创建游戏房间
                Room room = new Room();
                roomManager.add(room, user1.getUserId(), user2.getUserId());

                // 告诉玩家匹配成功
                session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(Result.success(user1.getUserName() + " " + user2.getUserName() +" 匹配成功", Constants.MATCH_SUCCESS))));
                session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(Result.success(user1.getUserName() + " " + user2.getUserName() +" 匹配成功", Constants.MATCH_SUCCESS))));
            }
        } catch (InterruptedException e) {
            log.info("MatcherService 提前被唤醒");
        } catch (IOException e) {
            log.info("handlerMatch IOException");
        }
    }
}
